#include "user_uart_obj.h"
#include "uart_obj.h"

#include "cw32f030_gpio.h"
#include "cw32f030_uart.h"
#include "cw32f030_rcc.h"
#include "cw32f030_dma.h"
#include "cw32f030_systick.h"
/*
	串口与功能对应关系
*/

/*---------------------------------------------串口1-对象-------------------------------------------------------------------*/
#define UART1_RX_FIFO_DEEP 2
#define UART1_RX_FIFO_SINGLE_BUFF_SIZE 128

uart_obj_t uart_obj1 = {0};

uint8_t uart1_tx_buf[128] = {0};

uint8_t uart1_rx_fifo_buf[UART1_RX_FIFO_DEEP * UART1_RX_FIFO_SINGLE_BUFF_SIZE] = {0};

rx_fifo_manage_t uart1_rx_fifo_manage[UART1_RX_FIFO_DEEP] = {0};

/*---------------------------------------------串口2-对象-------------------------------------------------------------------*/
// 假设串口2只使用发送功能
uart_obj_t uart_obj2 = {0};
uint8_t uart2_tx_buf[128] = {0};
/*----------------------------------------------内部函数声明------------------------------------------------------------*/
// 串口1
void cw32_uart1_send_data(uint8_t *udata, uint16_t len);

void uart1_tx_port_cb(uint8_t *udata, uint16_t len);
void uart1_fifo_rx_cb(uint8_t *rdata, uint16_t len);
void uart1_fifo_rx_stop_cb(void);
void uart1_fifo_rx_start_cb(uint8_t *rx_data, uint16_t len);
uint8_t uart1_get_rx_one_byte_cb(uint8_t *rx_data);

uint16_t cw32_uart1_get_dma_rx_current_cnt(void);
/*---------------------------------------------------------------------------------------------------------*/

/*------------------------------------------------------------cw32 串口外设初始化---------------------------------------------------------*/

void cw32_uart1_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure = {0};
	USART_InitTypeDef USART_InitStructure = {0};

	RCC_APBPeriphClk_Enable2(RCC_APB2_PERIPH_UART1, ENABLE);
	RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_GPIOA, ENABLE);

	PA08_AFx_UART1TXD();
	PA09_AFx_UART1RXD();

	GPIO_InitStructure.Pins = GPIO_PIN_8; // PA8
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
	GPIO_Init(CW_GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.Pins = GPIO_PIN_9; // PA9
	GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
	GPIO_Init(CW_GPIOA, &GPIO_InitStructure);

	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_Over = USART_Over_16;
	USART_InitStructure.USART_Source = USART_Source_PCLK;
	USART_InitStructure.USART_UclkFreq = 64000000;
	USART_InitStructure.USART_StartBit = USART_StartBit_FE;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(CW_UART1, &USART_InitStructure);

#if (CW32_UART1_MODE == UART_ONE_BYTE_IT_MODE)
	//  使能UARTx RC中断
	USART_ITConfig(CW_UART1, USART_IT_RC, ENABLE);
	// 优先级，无优先级分组
	NVIC_SetPriority(UART1_IRQn, 0);
	// UARTx中断使能
	NVIC_EnableIRQ(UART1_IRQn);
// #endif
#endif
}

void cw32_uart2_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_UART2, ENABLE);
	RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_GPIOA, ENABLE);

	PA02_AFx_UART2TXD();
	PA03_AFx_UART2RXD();

	GPIO_InitStructure.Pins = GPIO_PIN_2; // PA2
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
	GPIO_Init(CW_GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.Pins = GPIO_PIN_3; // PA3
	GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
	GPIO_Init(CW_GPIOA, &GPIO_InitStructure);

	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_Over = USART_Over_16;
	USART_InitStructure.USART_Source = USART_Source_PCLK;
	USART_InitStructure.USART_UclkFreq = 64000000;
	USART_InitStructure.USART_StartBit = USART_StartBit_FE;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(CW_UART2, &USART_InitStructure);

	// // 使能UARTx RC中断
	// USART_ITConfig(CW_UART2, USART_IT_RC, ENABLE);
	// // 优先级，无优先级分组
	// NVIC_SetPriority(UART2_IRQn, 0);
	// // UARTx中断使能
	// NVIC_EnableIRQ(UART2_IRQn);
}

void cw32_uart1_dma_init(void)
{
	// 串口1 TX -> DMA1 CH1

	__RCC_DMA_CLK_ENABLE();
	DMA_InitTypeDef DMA_InitStruct = {0};
	DMA_InitStruct.DMA_Mode = DMA_MODE_BLOCK;
	DMA_InitStruct.DMA_TransferWidth = DMA_TRANSFER_WIDTH_8BIT;
	DMA_InitStruct.DMA_SrcInc = DMA_SrcAddress_Increase;
	DMA_InitStruct.DMA_DstInc = DMA_DstAddress_Fix;
	DMA_InitStruct.DMA_TransferCnt = 0;
	DMA_InitStruct.DMA_SrcAddress = 0;
	DMA_InitStruct.DMA_DstAddress = 0;

	DMA_InitStruct.TrigMode = DMA_HardTrig;
	DMA_InitStruct.HardTrigSource = DMA_HardTrig_UART1_TXBufferE;

	DMA_Init(CW_DMACHANNEL1, &DMA_InitStruct);
	USART_DMACmd(CW_UART1, USART_DMAReq_Tx, ENABLE);

	// 串口1 RX -> DMA1 CH2
	DMA_InitStruct.DMA_SrcInc = DMA_SrcAddress_Fix;
	DMA_InitStruct.DMA_DstInc = DMA_DstAddress_Increase;
	DMA_InitStruct.HardTrigSource = DMA_HardTrig_UART1_RXBufferNE;

	DMA_Init(CW_DMACHANNEL2, &DMA_InitStruct);
	USART_DMACmd(CW_UART1, USART_DMAReq_Rx, ENABLE);

	/*
		中断分为两种
		DMA_IT_TC 传输完成中断：设定的接收数量传输完毕会产生中断
		DMA_IT_TE 错误中断：
		1. 地址错误会中断
		2. 主动终止传输会中断

		对于DMA传输来说，断帧时间到不用终止传输，重新设置传输长度即可
	*/
	//	DMA_ITConfig(CW_DMACHANNEL2, DMA_IT_TE, ENABLE);
	//	NVIC_ClearPendingIRQ(DMACH23_IRQn);
	//	NVIC_EnableIRQ(DMACH23_IRQn);
}

/*------------------------------------------------------------串口框架部分---------------------------------------------------------*/

// printf 重定向到串口 , 串口1作为printf

#include <stdio.h>

int fputc(int ch, FILE *stream)
{
	cw32_uart1_send_data((uint8_t *)&ch, 1);
	return ch;
}

/*---------------------------------------------------------------------------------------------------------------------*/

void bsp_uart_obj_init(void)
{
	// 串口1外设初始化
	cw32_uart1_init();
	cw32_uart1_dma_init();
	// 串口2外设初始化
	cw32_uart2_init();

	/*--------------------------------------串口1-对象初始化---------------------------------*/
	// 串口1对象初始化
	uart_obj_sta_t res = uart_obj_ok;
	uart_init_t uart_init = {0};

	// 串口模式选择
	uart_init.uart_mode = FW_UART_TX_RX; // 串口收发完整模式

	// 发送相关
	uart_init.tx_buf_addr = uart1_tx_buf;
	uart_init.tx_buf_size = sizeof(uart1_tx_buf);
	uart_init.uart_tx_port_cb = uart1_tx_port_cb;

	// 接收相关
	uart_init.rx_time_out_set = 5;										// 接收超时时间，单位ms
	uart_init.rx_fifo_buf_base_addr = uart1_rx_fifo_buf;				// 接收缓冲区基地址
	uart_init.rx_fifo_buf_size_single = UART1_RX_FIFO_SINGLE_BUFF_SIZE; // 单个缓冲区大小
	uart_init.rx_fifo_buf_size_total = sizeof(uart1_rx_fifo_buf);		// 接收缓冲区总大小

	uart_init.rx_fifo_deep = UART1_RX_FIFO_DEEP;	 // 接收FIFO深度
	uart_init.rx_fifo_manage = uart1_rx_fifo_manage; // 接收fifo管理结构体

	uart_init.uart_fifo_rx_cb = uart1_fifo_rx_cb; // 接收FIFO数据回调函数

	uart_init.uart_fifo_rx_stop_cb = uart1_fifo_rx_stop_cb;	  // 串口接收FIFO停止回调函数
	uart_init.uart_fifo_rx_start_cb = uart1_fifo_rx_start_cb; // 串口接收FIFO启动回调函数

#if (CW32_UART1_MODE == UART_ONE_BYTE_IT_MODE)
	// 单字节中断接口
	uart_init.uart_get_rx_one_byte_cb = uart1_get_rx_one_byte_cb;
	res = uart_obj_it_init(&uart_obj1, &uart_init);
#else
	uart_init.get_uart_dma_rx_current_cnt_cb = cw32_uart1_get_dma_rx_current_cnt;
	res = uart_obj_dma_init(&uart_obj1, &uart_init);
#endif
	if (res != uart_obj_ok)
	{
		while (1)
		{
		};
	}
	/*--------------------------------------串口2-对象初始化---------------------------------*/
	// 串口模式选择
	uart_init.uart_mode = FW_UART_TX_ONLY; // 假设只发送

	// 发送相关
	uart_init.tx_buf_addr = uart2_tx_buf;
	uart_init.tx_buf_size = sizeof(uart2_tx_buf);
	uart_init.uart_tx_port_cb = cw32_uart2_send_data;

	// 如果只发送不需要设置接收参数
	res = uart_obj_dma_init(&uart_obj2, &uart_init);
	if (res != uart_obj_ok)
	{
		while (1)
		{
		};
	}

	// uart_obj_printf(&uart_obj1, "[ msg ]: hello cw32f030. \r\n");
	// uart_obj_printf(&uart_obj1, "[ msg ]: this demo test high speed uart obj framework. \r\n");

	// 如果只是字符串数据 使用字符串发送省内存
	uart_obj_tx_str_data(&uart_obj1, "hello cw32f030. \r\n");
	uart_obj_tx_str_data(&uart_obj1, "this demo test high speed uart obj framework. \r\n");

	// 测试变量转字符串 , 其意义主要在于不使用可变形参，减少代码空间占用
	char str_buf[32] = {0};
	uart_obj_tx_str_data(&uart_obj1, "\r\ntest float to hex: ");
	uart_obj_tx_str_data(&uart_obj1, float_to_str_hex(123.4567, str_buf, sizeof(str_buf)));
	uart_obj_tx_str_data(&uart_obj1, "\r\ntest uint32 to hex: ");
	uart_obj_tx_str_data(&uart_obj1, uint_to_str_hex(123456, str_buf, sizeof(str_buf)));

	uart_obj_tx_str_data(&uart_obj1, "\r\ntest int32 to dec: ");
	uart_obj_tx_str_data(&uart_obj1, int_to_str_dec(-123456, str_buf, sizeof(str_buf)));
	uart_obj_tx_str_data(&uart_obj1, "\r\ntest uint32 to dec: ");
	uart_obj_tx_str_data(&uart_obj1, uint_to_str_dec(123456, str_buf, sizeof(str_buf)));
	uart_obj_tx_str_data(&uart_obj1, "\r\ntest float to dec: ");
	uart_obj_tx_str_data(&uart_obj1, float_to_str_dec(123.4567, str_buf, sizeof(str_buf), 4));
}

void cw32_uart1_send_data(uint8_t *udata, uint16_t len)
{
	while (len--)
	{
		USART_SendData_8bit(CW_UART1, *udata++);
		while (USART_GetFlagStatus(CW_UART1, USART_FLAG_TXE) == RESET)
		{
		};
	}
}

// 串口2发送函数接口
void cw32_uart2_send_data(uint8_t *data, uint16_t len)
{
	while (len--)
	{
		USART_SendData_8bit(CW_UART2, *data++);
		while (USART_GetFlagStatus(CW_UART2, USART_FLAG_TXE) == RESET)
		{
		};
	}
}

void cw32_uart1_dma_send_data(uint8_t *udata, uint16_t len)
{
	CW_DMACHANNEL1->CNT = bv16 | len;
	CW_DMACHANNEL1->SRCADDR = (uint32_t)udata;
	CW_DMACHANNEL1->DSTADDR = (uint32_t)&CW_UART1->TDR;
	DMA_Cmd(CW_DMACHANNEL1, ENABLE);
	// 加入等待传输完成
	while (DMA_GetFlagStatus(CW_DMACHANNEL1) != DMA_CHANNEL_STATUS_TRANSCOMPLETE)
	{
	}
	CW_DMACHANNEL1->CSR &= 0xff; // 清空传输状态
}

void cw32_uart1_rx_dma_start(uint8_t *rx_buf, uint16_t len)
{
	CW_DMACHANNEL2->CSR &= 0xff; // 清空传输状态
	CW_DMACHANNEL2->CNT = bv16 | len;
	CW_DMACHANNEL2->SRCADDR = (uint32_t)&(CW_UART1->RDR);
	CW_DMACHANNEL2->DSTADDR = (uint32_t)rx_buf;
	USART_ClearITPendingBit(CW_UART1, USART_IT_RC); // 清除标志位
	DMA_Cmd(CW_DMACHANNEL2, ENABLE);
	USART_DMACmd(CW_UART1, USART_DMAReq_Rx, ENABLE);
}

void cw32_uart1_rx_dma_stop(void)
{
	USART_DMACmd(CW_UART1, USART_DMAReq_Rx, DISABLE);
	USART_ClearITPendingBit(CW_UART1, USART_IT_RC); // 清除标志位
													// 不用暂停传输，暂停串口的就可以
													//  DMA_Cmd(CW_DMACHANNEL2, DISABLE);
}

uint16_t cw32_uart1_get_dma_rx_current_cnt(void)
{
	return CW_DMACHANNEL2->CNT_f.CNT;
}

void uart1_tx_port_cb(uint8_t *udata, uint16_t len)
{
#if (CW32_UART1_MODE == UART_ONE_BYTE_IT_MODE)
	cw32_uart1_send_data(udata, len);
#else
	cw32_uart1_dma_send_data(udata, len);
#endif
}

void uart1_fifo_rx_cb(uint8_t *rdata, uint16_t len)
{
	// 将接收到的数据发出
	uart_obj_tx_bin_data(&uart_obj1, rdata, len);
}

void uart1_fifo_rx_stop_cb(void)
{
#if (CW32_UART1_MODE == UART_ONE_BYTE_IT_MODE)
	USART_ITConfig(CW_UART1, USART_IT_RC, DISABLE);
#else
	cw32_uart1_rx_dma_stop();
#endif
}

void uart1_fifo_rx_start_cb(uint8_t *rx_data, uint16_t len)
{
#if (CW32_UART1_MODE == UART_ONE_BYTE_IT_MODE)
	USART_ITConfig(CW_UART1, USART_IT_RC, ENABLE);
#else
	cw32_uart1_rx_dma_start(rx_data, len);
#endif
}

uint8_t uart1_get_rx_one_byte_cb(uint8_t *rx_data)
{
	if (USART_GetITStatus(CW_UART1, USART_IT_RC) == RESET)
	{
		return 0;
	}
	USART_ClearITPendingBit(CW_UART1, USART_IT_RC); // 清除标志位
	*rx_data = USART_ReceiveData_8bit(CW_UART1);	// 读取接收到的数据
	return 1;
}

void task_uart1_it_rx_byte_irq(void)
{
#if (CW32_UART1_MODE == UART_ONE_BYTE_IT_MODE)
	uart_obj_it_rx_byte_irq(&uart_obj1);
#endif
}

void task_uart1_rx_frame_break(void)
{
#if (CW32_UART1_MODE == UART_ONE_BYTE_IT_MODE)
	uart_obj_it_rx_frame_break(&uart_obj1);
#else
	uart_obj_dma_rx_frame_break(&uart_obj1);
#endif
}

void task_uart1_rx_fifo_read(void)
{
	uart_obj_rx_fifo_read(&uart_obj1);
}
